// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: donggu

#pragma once

#include <experimental/filesystem>
#include <memory>
#include <optional>
#include <unordered_map>

#include "coin2/exchange/base/feed/arbitration/arbitration_config.h"

/**

Usage:

ConstantInjectionBuilder builder;
builder.feed_subscribers_toml = "data/coin2/my_custom_subscriber_info.toml";
ConstantInjection ci(builder);

auto product = Product::FromNative(ci, "BTC-USD...", ..);

**/

namespace coin2::exchange::base::symbology {
class ProductInfoConstant;
}

namespace coin2::flow {
class SymbolGroupConfig;
}

namespace coin2::exchange::base::market {
struct MarketExchangeApi;
}

namespace impl {
struct SymbologySpec;
}
using impl::SymbologySpec;
using coin2::exchange::base::feed::arbitration::impl::ArbitrationConfigMap;

struct FeedSubscriptionSpec;

namespace coin2::exchange::di {

struct ConstantInjectionBuilder {
  // for std::nullopt fields, the default path will be used
  std::optional<std::experimental::filesystem::path> symbology_specs_toml;
  std::optional<std::experimental::filesystem::path> feed_subscribers_toml;
  std::optional<std::experimental::filesystem::path> feed_symbol_groups_toml;
  std::optional<std::experimental::filesystem::path> product_info_dir;
  std::optional<std::experimental::filesystem::path> arbitration_config_toml;
};

class IConstantInjection;

class ConstantInjection {
 public:
  explicit ConstantInjection(const ConstantInjectionBuilder& builder, bool lazy_load = false);
  ~ConstantInjection();
  const SymbologySpec& GetSymbologySpec(
      const coin2::exchange::base::market::MarketExchangeApi& mea) const;
  const std::unordered_map<coin2::exchange::base::market::MarketExchangeApi, FeedSubscriptionSpec>&
  GetFeedSubscriptionSpecs() const;
  const FeedSubscriptionSpec& GetFeedSubscriptionSpec(
      const coin2::exchange::base::market::MarketExchangeApi& mea) const;
  const coin2::flow::SymbolGroupConfig& GetSymbolGroups() const;
  const coin2::exchange::base::symbology::ProductInfoConstant& GetProductInfo(
      const coin2::exchange::base::market::MarketExchangeApi& mea) const;
  const ArbitrationConfigMap& GetArbitrationConfigs() const;

 private:
  std::unique_ptr<IConstantInjection> impl_;
};

}  // namespace coin2::exchange::di
